﻿using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Server;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using WorkstationMes.Global;
using static WorkstationMes.Global.Events;

namespace Universal.Protocal.MQTT
{
    public class MqttServerService
    {
        private MqttServer server = null;
        private Dictionary<string, string> Clients = new Dictionary<string, string>()
        {
            {"OP10","OP10" },
            {"OP20","OP20" },
            {"OP30","OP30" },
            {"OP40","OP40" },
            {"OP50","OP50" },
            {"OP60","OP60" },
            {"Repair","Repair" }
        };
        
        public virtual void StartServer(string ip, int port)
        {
            var mqttServerOptions = new MqttServerOptionsBuilder()
                .WithDefaultEndpoint()
                .WithDefaultEndpointBoundIPAddress(IPAddress.Parse(ip))//set the ip of the server
                .WithDefaultEndpointPort(port)//set the port of the server
                .Build();
            server = new MqttFactory().CreateMqttServer(mqttServerOptions); // create MQTT service object
            server.ValidatingConnectionAsync += ValidatingConnectionAsync;
            server.ClientConnectedAsync += ClientConnectedAsync;
            server.ClientDisconnectedAsync += ClientDisconnectedAsync;
            server.ClientSubscribedTopicAsync += ClientSubscribedTopicAsync;
            server.ClientUnsubscribedTopicAsync += ClientUnsubscribedTopicAsync;
            server.InterceptingPublishAsync += InterceptingPublishAsync;
            server.ClientAcknowledgedPublishPacketAsync += ClientAcknowledgedPublishPacketAsync;
            server.InterceptingClientEnqueueAsync += InterceptingClientEnqueueAsync;
            server.ApplicationMessageNotConsumedAsync += ApplicationMessageNotConsumedAsync;
            server.StartedAsync += StartedAsync;
            server.StartAsync();
        }

        public virtual void SendMsg(string topic,string msg)
        {
            if(server != null)
            {
                server.InjectApplicationMessage(topic, msg);
            }
        }

        private void Log(string msg)
        {
            Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} : {msg}");
        }

        private async Task StartedAsync(EventArgs args)
        {
            await Task.Run(() =>
            {
                Log("Mqtt服务已启动");

                foreach(var item in Clients)
                {
                    server.SubscribeAsync(item.Key, "Collect");
                }                
            });
        }

        private async Task ApplicationMessageNotConsumedAsync(ApplicationMessageNotConsumedEventArgs args)
        {
            await Task.Run(() =>
            {

            });
        }

        private async Task InterceptingClientEnqueueAsync(InterceptingClientApplicationMessageEnqueueEventArgs args)
        {
            await Task.Run(() =>
            {

            });
        }

        private async Task ClientAcknowledgedPublishPacketAsync(ClientAcknowledgedPublishPacketEventArgs args)
        {
            await Task.Run(() =>
            {

            });
        }

        private async Task InterceptingPublishAsync(InterceptingPublishEventArgs args)
        {
            await Task.Run(() =>
            {
                if(args.ApplicationMessage.Topic == "Collect")
                {
                    List<string> datas = new List<string>()
                    {
                        args.ClientId,
                        Encoding.UTF8.GetString(args.ApplicationMessage.PayloadSegment.Array)
                    };
                    EventRepository.Events.GetEvent<CollectionEvent>().Publish(datas);
                }  
                else if(args.ApplicationMessage.Topic == "Repair")
                {
                    string matchCode = Encoding.UTF8.GetString(args.ApplicationMessage.PayloadSegment.Array);
                    EventRepository.Events.GetEvent<GetRepairProductEvent>().Publish(matchCode);
                }
            });
        }

        private async Task ClientUnsubscribedTopicAsync(ClientUnsubscribedTopicEventArgs args)
        {
            await Task.Run(() =>
            {

            });
        }

        private async Task ClientSubscribedTopicAsync(ClientSubscribedTopicEventArgs args)
        {
            await Task.Run(() =>
            {
                Log(args.ClientId + "  :  " + args.TopicFilter.Topic);
            });
        }

        private async Task ClientDisconnectedAsync(ClientDisconnectedEventArgs args)
        {
            await Task.Run(() =>
            {

            });
        }

        private async Task ClientConnectedAsync(ClientConnectedEventArgs args)
        {
            await Task.Run(() =>
            {
                Log(args.ClientId + "已连接");
            });
        }

        private async Task ValidatingConnectionAsync(ValidatingConnectionEventArgs args)
        {
            await Task.Run(() =>
            {
                if (Clients.ContainsKey(args.UserName))
                {
                    if (Clients[args.UserName] == args.Password)
                    {
                        args.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.Success;
                    }
                }
                else
                {
                    args.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.ClientIdentifierNotValid;                    
                }
            });
        }
    }
}
